package com.huabo.schedule;

import com.huabo.dao.inter.TimerJobDao;
import com.huabo.model.TimerJob;
import com.huabo.service.inter.DataService;
import com.huabo.utils.SpringContextHelper;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.SchedulerException;
import org.springframework.context.ApplicationContext;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * Created by Jackie Liu on 2017/8/2.
 */
public abstract class AbstractJobFactory {

    private static final String APPLICATION_CONTEXT_KEY = "applicationContextKey";
    //获取spring的上下文
    protected ApplicationContext getApplicationContext(JobExecutionContext context) {
        ApplicationContext appCtx = null;
        try {
            appCtx = (ApplicationContext) context.getScheduler().getContext().get(APPLICATION_CONTEXT_KEY);
            if (appCtx == null) {
                throw new JobExecutionException("No application context available in scheduler context for key \"" + APPLICATION_CONTEXT_KEY + "\"");
            }
        } catch (SchedulerException e) {
            e.printStackTrace();
        }
        return appCtx;
    }

    protected void invoke(ScheduleJob job) {
        if (StringUtils.isEmpty(job.getJobClassName())) {
            return;
        }
        before(job);
        try {
            Class<?> clazz = Class.forName(job.getJobClassName());
            //从spring容器获取bean,否则无法注入
            Object obj = SpringContextHelper.getBean(clazz);
            //反射方法
            Method method = obj.getClass().getDeclaredMethod(job.getJobMethodName(), new Class[]{ScheduleJob.class});
            method.invoke(obj, job);
            after(job);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            exception(job, e);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
            exception(job, e);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
            exception(job, e);
        } catch (InvocationTargetException e) {
            e.printStackTrace();
            exception(job, e);
        }
    }

    protected void before(ScheduleJob job) {
        try {
            TimerJob timerJob = new TimerJob();
            timerJob.setId(job.getJobId());
            timerJob.setState(TimerJob.Status.RUNNING.getValue());

            TimerJobDao timerJobDao = SpringContextHelper.getBean(TimerJobDao.class);
            timerJobDao.update(timerJob);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    protected void after(ScheduleJob job) {
        try {
            TimerJob timerJob = new TimerJob();
            timerJob.setId(job.getJobId());
            timerJob.setState(TimerJob.Status.JOIN.getValue());

            TimerJobDao timerJobDao = SpringContextHelper.getBean(TimerJobDao.class);
            timerJobDao.update(timerJob);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    protected void exception(ScheduleJob job, Exception e) {
        try {
            TimerJob timerJob = new TimerJob();
            timerJob.setId(job.getJobId());
            timerJob.setState(TimerJob.Status.ERROR.getValue());
            //timerJob.setErrorMessage(ExceptionUtils.getStackTrace(e));

            String errorMessage = e.getMessage() + "\n" + ExceptionUtils.getStackTrace(e);

            DataService dataService = SpringContextHelper.getBean(DataService.class);
            dataService.saveOrUpdate(job.getJobId(), errorMessage);

            TimerJobDao timerJobDao = SpringContextHelper.getBean(TimerJobDao.class);
            timerJobDao.update(timerJob);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}
